<template>
  <div class="custom-calendar">
    <!-- 日历头部 -->
    <div class="calendar-header">
      <div class="calendar-nav">
        <el-button @click="previousWeek" size="small" type="text">
          <i class="el-icon-arrow-left"></i> 上一周
        </el-button>
        <span class="current-week">{{ formatWeekRange(currentWeekStart) }}</span>
        <el-button @click="nextWeek" size="small" type="text">
          下一周 <i class="el-icon-arrow-right"></i>
        </el-button>
      </div>
      <div class="calendar-actions">
        <el-button @click="goToToday" size="small">今天</el-button>
        <el-button @click="testDrawer" size="small" type="danger">测试抽屉</el-button>
        <el-button @click="forceShowDialog" size="small" type="warning"
          >强制显示</el-button
        >
      </div>
    </div>

    <!-- 日历主体 -->
    <div class="calendar-body">
      <div class="calendar-grid">
        <!-- 时间列和日期头部 -->
        <div class="calendar-header-row">
          <div class="time-header-cell">时间</div>
          <div v-for="day in weekDays" :key="day.date" class="day-header-cell">
            <div class="day-name">{{ day.name }}</div>
            <div class="day-date">{{ day.date }}</div>
          </div>
        </div>

        <!-- 时间行和事件网格 -->
        <div class="calendar-content">
          <div class="time-column">
            <div v-for="time in timeSlots" :key="time" class="time-slot">
              {{ time }}
            </div>
          </div>

          <div class="days-grid">
            <div
              v-for="day in weekDays"
              :key="day.fullDate"
              class="day-column"
              @mousemove="handleMouseMove"
              @mouseleave="handleMouseLeave"
            >
              <div class="hour-slots">
                <div
                  v-for="(hour, index) in 24"
                  :key="`${day.fullDate}-${hour}`"
                  class="hour-slot"
                  :class="{ 'has-event': hasEvent(day.fullDate, index) }"
                  :style="{ height: '60px', position: 'relative' }"
                  @click="handleSlotClick(day.fullDate, index, $event)"
                >
                  <!-- 添加按钮提示 -->
                  <div
                    v-if="!hasEvent(day.fullDate, index) && canEdit"
                    class="add-hint"
                    style="
                      position: absolute;
                      top: 50%;
                      left: 50%;
                      transform: translate(-50%, -50%);
                      opacity: 0;
                      transition: opacity 0.2s;
                      pointer-events: none;
                    "
                  >
                    <i class="el-icon-plus" style="font-size: 12px; color: #409eff"></i>
                  </div>
                </div>

                <!-- 任务块 - 移出小时槽，只在每天列中渲染一次 -->
                <div
                  v-for="event in getEventsForDay(day.fullDate)"
                  :key="event.id"
                  v-show="isEventVisible(event)"
                  class="event-block"
                  :class="{
                    editable: canEdit,
                    resizable: canEdit,
                    'hover-top': isHoveringTop(event, $event),
                    'hover-bottom': isHoveringBottom(event, $event),
                    'drag-over': isDragOverEvent === event.id
                  }"
                  :style="getEventStyle(event)"
                  @click="handleEventClick(event)"
                  @mousedown="handleEventMouseDown($event, event)"
                  @mousemove="handleEventMouseMove($event, event)"
                  @dragover.prevent="handleEventDragOver(event)"
                  @dragleave="handleEventDragLeave"
                  @drop="handleEventDrop($event, event)"
                >
                  <div class="event-content">
                    <div class="event-title">{{ event.title }}</div>
                    <div class="event-time">{{ formatEventTime(event) }}</div>
                    <div class="event-tech">
                      {{ getTechnicianName(event.technician) }}
                    </div>
                  </div>

                  <!-- 调整手柄 -->
                  <div v-if="canEdit" class="resize-handles">
                    <div
                      class="resize-handle top"
                      @mousedown.stop="handleResizeStart($event, event, 'top')"
                    ></div>
                    <div
                      class="resize-handle bottom"
                      @mousedown.stop="handleResizeStart($event, event, 'bottom')"
                    ></div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 事件详情抽屉 -->
    <el-drawer
      :title="selectedEvent ? '排班详情' : '创建排班'"
      v-model="showDialog"
      direction="rtl"
      size="400px"
      :before-close="handleDrawerClose"
      :append-to-body="true"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :show-close="true"
    >
      <div class="drawer-content">
        <el-form :model="eventForm" label-width="80px" class="drawer-form">
          <el-form-item label="标题">
            <el-input v-model="eventForm.title" placeholder="请输入排班标题" />
          </el-form-item>
          <el-form-item label="员工">
            <el-select
              v-model="eventForm.technician"
              placeholder="选择员工"
              filterable
              :disabled="!canEdit"
              style="width: 100%"
            >
              <el-option
                v-for="employee in employees"
                :key="employee.id"
                :label="employee.username"
                :value="employee.id"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="开始时间">
            <el-date-picker
              v-model="eventForm.start"
              type="datetime"
              placeholder="选择开始时间"
              :disabled="!canEdit"
              style="width: 100%"
            />
          </el-form-item>
          <el-form-item label="结束时间">
            <el-date-picker
              v-model="eventForm.end"
              type="datetime"
              placeholder="选择结束时间"
              :disabled="!canEdit"
              style="width: 100%"
            />
          </el-form-item>
          <el-form-item label="颜色">
            <el-color-picker
              v-model="eventForm.color"
              :disabled="!canEdit"
              :predefine="[
                '#3788d8',
                '#ff6b6b',
                '#4ecdc4',
                '#45b7d1',
                '#96ceb4',
                '#feca57',
                '#ff9ff3',
                '#54a0ff',
                '#5f27cd',
                '#00d2d3',
                '#ff9f43',
                '#10ac84'
              ]"
            />
          </el-form-item>
          <el-form-item label="备注">
            <el-input
              v-model="eventForm.notes"
              type="textarea"
              :rows="3"
              placeholder="添加备注信息"
              :disabled="!canEdit"
            />
          </el-form-item>
        </el-form>
        <div class="drawer-footer">
          <el-button @click="showDialog = false">关闭</el-button>
          <el-button v-if="canEdit && selectedEvent" type="danger" @click="deleteEvent"
            >删除</el-button
          >
          <el-button v-if="canEdit" type="primary" @click="saveEvent">保存</el-button>
        </div>
      </div>
    </el-drawer>
  </div>
</template>

<script>
import request from "@/utils/request";

export default {
  name: "CustomCalendar",
  props: {
    events: {
      type: Array,
      default: () => [],
    },
    employees: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      currentWeekStart: new Date(),
      selectedEvent: null,
      showDialog: false,
      eventForm: {
        id: null,
        title: "",
        technician: "",
        start: null,
        end: null,
        notes: "",
      },
      draggingEvent: null,
      resizingEvent: null,
      resizeDirection: null,
      dragStartY: 0,
      dragStartTime: null,
      hoverEvent: null,
      mouseY: 0,
      eventsCache: new Map(),
      isDragOverEvent: null,
    };
  },
  computed: {
    weekDays() {
      const days = [];
      const start = this.getWeekStart(this.currentWeekStart);

      for (let i = 0; i < 7; i++) {
        const date = new Date(start);
        date.setDate(start.getDate() + i);

        days.push({
          name: ["周日", "周一", "周二", "周三", "周四", "周五", "周六"][date.getDay()],
          date: date.getDate(),
          fullDate: date.toISOString().split("T")[0],
        });
      }

      return days;
    },
    timeSlots() {
      const slots = [];
      for (let i = 0; i < 24; i++) {
        slots.push(`${i.toString().padStart(2, "0")}:00`);
      }
      return slots;
    },
    canEdit() {
      const userStr = localStorage.getItem("user");
      if (!userStr) return false;

      try {
        const user = JSON.parse(userStr);
        return user.role === "老板" || user.role === "管理员";
      } catch (error) {
        console.error("解析用户信息失败:", error);
        return false;
      }
    },
  },
  watch: {
    currentWeekStart(newWeek) {
      this.$emit("week-changed", this.getWeekStart(newWeek));
    },
    events: {
      handler() {
        this.eventsCache.clear();
      },
      deep: true,
    },
  },

  methods: {
    handleDrawerClose(done) {
      done();
    },

    // 鼠标悬停检测
    handleMouseMove(event) {
      this.mouseY = event.offsetY;
    },

    handleMouseLeave() {
      this.hoverEvent = null;
    },

    isHoveringTop(event, mouseEvent) {
      if (!mouseEvent) return false;
      const eventTop = this.getEventTop(event);
      const relativeY = this.mouseY - eventTop;
      return relativeY <= 10 && this.canEdit;
    },

    isHoveringBottom(event, mouseEvent) {
      if (!mouseEvent) return false;
      const eventTop = this.getEventTop(event);
      const eventHeight = this.getEventHeight(event);
      const relativeY = this.mouseY - eventTop;
      return relativeY >= eventHeight - 10 && this.canEdit;
    },

    getEventTop(event) {
      const start = new Date(event.start);
      const hour = start.getHours();
      const minutes = start.getMinutes();
      return hour * 60 + (minutes / 60) * 60;
    },

    getEventHeight(event) {
      const start = new Date(event.start);
      const end = new Date(event.end);
      const duration = (end - start) / (1000 * 60 * 60);
      return duration * 60;
    },

    // 事件点击 - 所有用户都可以查看
    handleEventClick(event) {
      this.selectedEvent = event;

      // 调试日志
      console.log("点击事件:", event);
      console.log("技师信息:", event.technician);

      // 处理技师数据格式
      let technicianId = "";
      if (event.technician) {
        if (typeof event.technician === "object") {
          technicianId = event.technician._id || event.technician.id || "";
        } else {
          technicianId = event.technician;
        }
      }

      this.eventForm = {
        id: event.id || event._id,
        title: event.title,
        technician: technicianId,
        start: new Date(event.start),
        end: new Date(event.end),
        color: event.color || '#3788d8',
        notes: event.notes || "",
      };

      
      this.showDialog = true;
    },

    // 鼠标悬停事件处理
    handleEventMouseMove(event, schedule, mouseEvent) {
      if (!this.canEdit || !mouseEvent) return;

      const relativeY = mouseEvent.offsetY;
      const height = mouseEvent.target.offsetHeight;

      // 增加检测区域，更容易触发调整手柄
      const edgeThreshold = Math.max(12, height * 0.15); // 至少12px或15%高度

      if (relativeY <= edgeThreshold) {
        mouseEvent.target.style.cursor = "ns-resize";
        mouseEvent.target.title = "调整开始时间";
        mouseEvent.target.classList.add("hover-top");
        mouseEvent.target.classList.remove("hover-bottom");
      } else if (relativeY >= height - edgeThreshold) {
        mouseEvent.target.style.cursor = "ns-resize";
        mouseEvent.target.title = "调整结束时间";
        mouseEvent.target.classList.add("hover-bottom");
        mouseEvent.target.classList.remove("hover-top");
      } else {
        mouseEvent.target.style.cursor = "grab";
        mouseEvent.target.title = "拖拽调整时间（上下移动）";
        mouseEvent.target.classList.remove("hover-top", "hover-bottom");
      }
    },

    // 拖拽功能
    handleEventMouseDown(event, schedule) {
      if (!this.canEdit) return;

      const target = event.target.closest(".event-block");
      const rect = target.getBoundingClientRect();
      const relativeY = event.offsetY;
      const height = target.offsetHeight;

      // 增加检测区域，更容易触发调整手柄
      const edgeThreshold = Math.max(12, height * 0.15);

      // 检查是否在边缘
      if (relativeY <= edgeThreshold) {
        this.handleResizeStart(event, schedule, "top");
        target.classList.add("resizing");
      } else if (relativeY >= height - edgeThreshold) {
        this.handleResizeStart(event, schedule, "bottom");
        target.classList.add("resizing");
      } else {
        // 拖拽整个事件
        event.preventDefault();
        this.draggingEvent = schedule;
        this.dragStartY = event.clientY;
        this.dragStartTime = new Date(schedule.start);
        target.classList.add("dragging");

        document.addEventListener("mousemove", this.handleDrag);
        document.addEventListener("mouseup", this.handleDragEnd);
      }
    },

    getEventsForDay(date) {
      const targetDate = new Date(date);
      targetDate.setHours(0, 0, 0, 0);

      const nextDate = new Date(targetDate);
      nextDate.setDate(nextDate.getDate() + 1);

      // 使用缓存避免重复计算
      const cacheKey = date;
      if (this.eventsCache.has(cacheKey)) {
        return this.eventsCache.get(cacheKey);
      }

      // 获取当天的事件
      const dayEvents = this.events.filter((event) => {
        if (!event || !event.start || !event.end) return false;

        const eventStart = new Date(event.start);
        const eventEnd = new Date(event.end);

        // 确保事件有有效的时间范围
        if (isNaN(eventStart.getTime()) || isNaN(eventEnd.getTime())) {
          return false;
        }

        return eventStart < nextDate && eventEnd > targetDate;
      });

      // 调试：检查重复事件
      if (process.env.NODE_ENV === "development") {
        const originalCount = dayEvents.length;
        const eventIds = dayEvents.map((e) => e.id || e._id).filter(Boolean);
        const duplicateIds = eventIds.filter(
          (id, index) => eventIds.indexOf(id) !== index
        );

        if (duplicateIds.length > 0) {
          console.warn(`日期 ${date} 发现重复事件ID:`, duplicateIds);
        }

        console.log(
          `日期 ${date} 原始事件数: ${originalCount}, 唯一事件数: ${
            new Set(eventIds).size
          }`
        );
      }

      // 去重：基于事件ID
      const uniqueEvents = [];
      const seenIds = new Set();

      dayEvents.forEach((event) => {
        const eventId = event.id || event._id;
        if (eventId && !seenIds.has(eventId)) {
          seenIds.add(eventId);
          uniqueEvents.push(event);
        } else if (!eventId) {
          // 没有ID的事件，使用内容和时间作为唯一标识
          const uniqueKey = `${event.title}_${event.start}_${event.end}`;
          if (!seenIds.has(uniqueKey)) {
            seenIds.add(uniqueKey);
            uniqueEvents.push(event);
          }
        }
      });

      // 按开始时间排序
      uniqueEvents.sort((a, b) => new Date(a.start) - new Date(b.start));

      // 计算事件位置，避免重叠
      const positionedEvents = this.calculateEventPositions(uniqueEvents);

      // 缓存结果
      this.eventsCache.set(cacheKey, positionedEvents);

      return positionedEvents;
    },

    calculateEventPositions(events) {
      if (!events.length) return events;

      const positionedEvents = events.map((event) => ({
        ...event,
        position: { left: 0, width: 100, level: 0 },
      }));

      // 计算重叠的事件组
      const groups = [];
      let currentGroup = [positionedEvents[0]];

      for (let i = 1; i < positionedEvents.length; i++) {
        const currentEvent = positionedEvents[i];
        const prevEvent = currentGroup[currentGroup.length - 1];

        const currentStart = new Date(currentEvent.start);
        const currentEnd = new Date(currentEvent.end);
        const prevStart = new Date(prevEvent.start);
        const prevEnd = new Date(prevEvent.end);

        if (currentStart < prevEnd) {
          // 有重叠，加入当前组
          currentGroup.push(currentEvent);
        } else {
          // 无重叠，开始新组
          groups.push(currentGroup);
          currentGroup = [currentEvent];
        }
      }
      groups.push(currentGroup);

      // 为每组事件计算位置
      groups.forEach((group) => {
        const levels = [];

        group.forEach((event) => {
          let level = 0;
          let placed = false;

          while (!placed) {
            if (!levels[level]) {
              levels[level] = [event];
              event.position.level = level;
              placed = true;
            } else {
              const lastEvent = levels[level][levels[level].length - 1];
              const lastEnd = new Date(lastEvent.end);
              const currentStart = new Date(event.start);

              if (currentStart >= lastEnd) {
                levels[level].push(event);
                event.position.level = level;
                placed = true;
              } else {
                level++;
              }
            }
          }
        });

        const maxLevel = Math.max(...group.map((e) => e.position.level)) + 1;
        const width = 100 / maxLevel;

        group.forEach((event) => {
          event.position.width = width - 2;
          event.position.left = event.position.level * width + 1;
        });
      });

      return positionedEvents;
    },

    getEventStyle(event) {
      const start = new Date(event.start);
      const end = new Date(event.end);

      // 确保事件在时间范围内
      const dayStart = new Date(start);
      dayStart.setHours(0, 0, 0, 0);
      const dayEnd = new Date(dayStart);
      dayEnd.setHours(23, 59, 59, 999);

      // 计算可见的开始和结束时间
      const visibleStart = new Date(Math.max(start.getTime(), dayStart.getTime()));
      const visibleEnd = new Date(Math.min(end.getTime(), dayEnd.getTime()));

      const duration = (visibleEnd - visibleStart) / (1000 * 60 * 60);
      const hour = visibleStart.getHours();
      const minutes = visibleStart.getMinutes();
      const topOffset = hour * 60 + (minutes / 60) * 60;

      // 最小高度为25px，确保能显示完整信息
      const height = Math.max(duration * 60, 25);

      // 使用计算好的位置信息
      const left = event.position?.left || 1;
      const width = event.position?.width || 98;

      return {
        height: `${height}px`,
        backgroundColor: event.color || "#3788d8",
        top: `${topOffset}px`,
        position: "absolute",
        left: `${left}%`,
        width: `${width}%`,
        zIndex: 10,
        minHeight: "25px",
        borderRadius: "4px",
        boxSizing: "border-box",
      };
    },

    formatEventTime(event) {
      const start = new Date(event.start);
      const end = new Date(event.end);
      const startHour = start.getHours();
      const startMin = start.getMinutes();
      const endHour = end.getHours();
      const endMin = end.getMinutes();

      return `${startHour}:${startMin
        .toString()
        .padStart(2, "0")} - ${endHour}:${endMin.toString().padStart(2, "0")}`;
    },

    // 确保事件在可视范围内
    isEventVisible(event) {
      const start = new Date(event.start);
      const end = new Date(event.end);

      // 检查事件是否在当天的24小时内
      const dayStart = new Date(start);
      dayStart.setHours(0, 0, 0, 0);
      const dayEnd = new Date(dayStart);
      dayEnd.setHours(23, 59, 59, 999);

      return end > dayStart && start < dayEnd;
    },

    hasEvent(date, hour) {
      return this.getEventsForDay(date).some((event) => {
        const eventStart = new Date(event.start);
        const eventEnd = new Date(event.end);
        const eventStartHour = eventStart.getHours();
        const eventEndHour = eventEnd.getHours();
        return (
          eventStartHour === hour || (eventStartHour <= hour && eventEndHour >= hour)
        );
      });
    },

    // 拖拽功能 - 精准版本
    handleDrag(event) {
      if (!this.draggingEvent) return;

      event.preventDefault();
      const deltaY = event.clientY - this.dragStartY;
      const deltaMinutes = Math.round(deltaY); // 每像素 = 1分钟

      const originalDuration =
        new Date(this.draggingEvent.end) - new Date(this.draggingEvent.start);

      let newStart = new Date(this.dragStartTime);
      newStart.setMinutes(newStart.getMinutes() + deltaMinutes);

      let newEnd = new Date(newStart.getTime() + originalDuration);

      // 限制在当天的24小时内，确保不会消失
      const dayStart = new Date(newStart);
      dayStart.setHours(0, 0, 0, 0);
      const dayEnd = new Date(dayStart);
      dayEnd.setHours(23, 59, 59, 999);

      // 确保最小事件时长为30分钟
      const minDuration = 30 * 60 * 1000; // 30分钟

      if (newStart < dayStart) {
        newStart = new Date(dayStart);
        newEnd = new Date(newStart.getTime() + Math.max(originalDuration, minDuration));
      } else if (newEnd > dayEnd) {
        newEnd = new Date(dayEnd);
        newStart = new Date(newEnd.getTime() - Math.max(originalDuration, minDuration));
      }

      // 确保不会超出当天范围
      if (newStart < dayStart) newStart = new Date(dayStart);
      if (newEnd > dayEnd) newEnd = new Date(dayEnd);

      // 再次检查最小时长
      if (newEnd - newStart < minDuration) {
        if (newEnd.getTime() === dayEnd.getTime()) {
          newStart = new Date(newEnd.getTime() - minDuration);
        } else {
          newEnd = new Date(newStart.getTime() + minDuration);
        }
      }

      // 确保最终也在范围内
      if (newStart < dayStart) newStart = new Date(dayStart);
      if (newEnd > dayEnd) newEnd = new Date(dayEnd);

      // 临时更新显示
      this.draggingEvent.start = newStart;
      this.draggingEvent.end = newEnd;
    },

    handleDragEnd() {
      // 移除所有拖拽相关的视觉反馈类
      const eventElements = document.querySelectorAll(".event-block");
      eventElements.forEach((el) => {
        el.classList.remove("dragging", "resizing");
      });

      if (!this.draggingEvent) return;

      // 更新eventForm为拖拽的事件
      this.eventForm = {
        id: this.draggingEvent.id,
        title: this.draggingEvent.title,
        technician: this.draggingEvent.technician?._id || this.draggingEvent.technician,
        start: new Date(this.draggingEvent.start),
        end: new Date(this.draggingEvent.end),
        notes: this.draggingEvent.notes || "",
      };

      // 静默保存，不显示抽屉
      this.saveEventSilently();

      this.draggingEvent = null;
      this.dragStartY = 0;
      this.dragStartTime = null;

      document.removeEventListener("mousemove", this.handleDrag);
      document.removeEventListener("mouseup", this.handleDragEnd);
    },

    // 静默保存事件（拖拽后使用）
    async saveEventSilently() {
      try {
        const formData = {
          title: this.eventForm.title,
          technician: this.eventForm.technician,
          start: this.eventForm.start,
          end: this.eventForm.end,
          color: this.eventForm.color,
          notes: this.eventForm.notes,
        };

        if (this.eventForm.id) {
          await request.put(`/api/schedules/events/${this.eventForm.id}`, formData);
          this.$emit("event-updated");
        } else {
          await request.post("/api/schedules/events", formData);
          this.$emit("event-updated");
        }
      } catch (error) {
        console.error("保存失败:", error);
        // 拖拽失败时恢复原位置
        this.$emit("event-updated");
      }
    },

    // 调整大小功能
    handleResizeStart(event, schedule, direction) {
      if (!this.canEdit) return;

      event.preventDefault();
      this.resizingEvent = schedule;
      this.resizeDirection = direction;
      this.dragStartY = event.clientY;

      document.addEventListener("mousemove", this.handleResize);
      document.addEventListener("mouseup", this.handleResizeEnd);
    },

    handleResize(event) {
      if (!this.resizingEvent) return;

      event.preventDefault();
      const deltaY = event.clientY - this.dragStartY;
      const deltaMinutes = Math.round(deltaY); // 每像素 = 1分钟，更精准

      const minDuration = 30 * 60 * 1000; // 最小30分钟
      const originalStart = new Date(this.resizingEvent.start);
      const originalEnd = new Date(this.resizingEvent.end);

      // 限制在当天的24小时内
      const dayStart = new Date(originalStart);
      dayStart.setHours(0, 0, 0, 0);
      const dayEnd = new Date(dayStart);
      dayEnd.setHours(23, 59, 59, 999);

      if (this.resizeDirection === "top") {
        // 调整开始时间
        let newStart = new Date(originalStart);
        newStart.setMinutes(newStart.getMinutes() + deltaMinutes);

        // 确保不会早于当天开始
        if (newStart < dayStart) {
          newStart = new Date(dayStart);
        }

        // 确保不会晚于结束时间减最小时长
        const maxStart = new Date(originalEnd.getTime() - minDuration);
        if (newStart > maxStart) {
          newStart = maxStart;
        }

        // 再次检查最小时长
        if (originalEnd.getTime() - newStart.getTime() < minDuration) {
          newStart = new Date(originalEnd.getTime() - minDuration);
        }

        // 确保最终也在范围内
        if (newStart < dayStart) newStart = new Date(dayStart);

        this.resizingEvent.start = newStart;
      } else {
        // 调整结束时间
        let newEnd = new Date(originalEnd);
        newEnd.setMinutes(newEnd.getMinutes() + deltaMinutes);

        // 确保不会晚于当天结束
        if (newEnd > dayEnd) {
          newEnd = new Date(dayEnd);
        }

        // 确保不会早于开始时间加最小时长
        const minEnd = new Date(originalStart.getTime() + minDuration);
        if (newEnd < minEnd) {
          newEnd = minEnd;
        }

        // 再次检查最小时长
        if (newEnd.getTime() - originalStart.getTime() < minDuration) {
          newEnd = new Date(originalStart.getTime() + minDuration);
        }

        // 确保最终也在范围内
        if (newEnd > dayEnd) newEnd = new Date(dayEnd);

        this.resizingEvent.end = newEnd;
      }
    },

    handleResizeEnd() {
      if (!this.resizingEvent) return;

      // 更新eventForm为调整大小的事件
      this.eventForm = {
        id: this.resizingEvent.id,
        title: this.resizingEvent.title,
        technician: this.resizingEvent.technician?._id || this.resizingEvent.technician,
        start: new Date(this.resizingEvent.start),
        end: new Date(this.resizingEvent.end),
        notes: this.resizingEvent.notes || "",
      };

      // 静默保存，不显示抽屉
      this.saveEventSilently();

      this.resizingEvent = null;
      this.resizeDirection = null;
      this.dragStartY = 0;

      document.removeEventListener("mousemove", this.handleResize);
      document.removeEventListener("mouseup", this.handleResizeEnd);
    },

    // 其他方法
    getWeekStart(date) {
      const d = new Date(date);
      const day = d.getDay();
      const diff = d.getDate() - day + (day === 0 ? -6 : 1);
      const weekStart = new Date(d.setDate(diff));
      weekStart.setHours(0, 0, 0, 0);
      return weekStart;
    },

    formatWeekRange(date) {
      const start = this.getWeekStart(date);
      const end = new Date(start);
      end.setDate(start.getDate() + 6);
      return `${start.getMonth() + 1}月${start.getDate()}日 - ${
        end.getMonth() + 1
      }月${end.getDate()}日`;
    },

    previousWeek() {
      const newDate = new Date(this.currentWeekStart);
      newDate.setDate(newDate.getDate() - 7);
      this.currentWeekStart = newDate;
    },

    nextWeek() {
      const newDate = new Date(this.currentWeekStart);
      newDate.setDate(newDate.getDate() + 7);
      this.currentWeekStart = newDate;
    },

    goToToday() {
      this.currentWeekStart = new Date();
    },

    handleSlotClick(date, hour, event) {
      console.log("点击空白格子触发:", date, hour, this.canEdit);
      if (!this.canEdit) {
        console.log("当前用户无编辑权限");
        return;
      }

      // 计算精确的点击时间
      const minutes = Math.round((event.offsetY / 60) * 60);
      const startTime = new Date(date);
      startTime.setHours(hour, minutes, 0, 0);

      const endTime = new Date(startTime);
      endTime.setHours(startTime.getHours() + 1);

      this.selectedEvent = null;
      this.eventForm = {
        id: null,
        title: "新排班",
        technician: "",
        start: startTime,
        end: endTime,
        color: '#3788d8',
        notes: "",
      };
      this.showDialog = true;
    },

    async saveEvent() {
      try {
        const formData = {
          title: this.eventForm.title,
          technician: this.eventForm.technician,
          start: this.eventForm.start,
          end: this.eventForm.end,
          color: this.eventForm.color,
          notes: this.eventForm.notes,
        };

        if (this.eventForm.id) {
          await request.put(`/api/schedules/events/${this.eventForm.id}`, formData);
        } else {
          await request.post("/api/schedules/events", formData);
        }

        this.$emit("event-updated");
        this.showDialog = false;
      } catch (error) {
        this.$message.error("保存失败");
      }
    },

    async deleteEvent() {
      try {
        await this.$confirm("确定要删除这个排班吗？", "确认删除", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        });

        await request.delete(`/api/schedules/events/${this.eventForm.id}`);
        this.$emit("event-deleted");
        this.showDialog = false;
      } catch (error) {
        if (error !== "cancel") {
          this.$message.error("删除失败");
        }
      }
    },

    // 拖拽相关方法
    handleEventDragOver(event) {
      if (this.canEdit) {
        this.isDragOverEvent = event.id;
      }
    },
    
    handleEventDragLeave() {
      this.isDragOverEvent = null;
    },
    
    async handleEventDrop(dropEvent, targetEvent) {
      if (!this.canEdit) return;
      
      this.isDragOverEvent = null;
      
      try {
        const dragData = JSON.parse(dropEvent.dataTransfer.getData('application/json'));
        
        if (dragData.type === 'employee') {
          const employee = dragData.employee;
          console.log("====",employee);
          
          // 检查时间冲突
          const conflict = await this.checkTimeConflict(
            employee.id, 
            new Date(targetEvent.start), 
            new Date(targetEvent.end), 
            targetEvent.id
          );
          
          if (conflict) {
            this.$message.warning('该员工在此时间段已有排班');
            return;
          }
          
          // 更新事件
          const updatedEvent = {
            ...targetEvent,
            technician: employee.id,
            title: targetEvent.title || '工作安排'
          };
          
          // 保存更新
          await request.put(`/api/schedules/events/${targetEvent.id}`, updatedEvent);
          
          // 通知父组件刷新数据
          this.$emit('event-updated');
          
          this.$message.success(`已将 ${employee.username} 分配到该排班`);
        }
      } catch (error) {
        console.error('拖拽分配失败:', error);
        this.$message.error('分配失败');
      }
    },
    
    async checkTimeConflict(technicianId, start, end, excludeId = null) {
      try {
        if (!technicianId) return false;
        
        const params = {
          technicianId,
          start: start.toISOString(),
          end: end.toISOString()
        };
        
        if (excludeId) {
          params.excludeId = excludeId;
        }
        
        const response = await request.get('/api/schedules/check-conflict', { params });
        return response.data.hasConflict;
      } catch (error) {
        console.error('检查时间冲突失败:', error);
        return false;
      }
    },

    // 根据技师ID获取技师名称
    getTechnicianName(technicianId) {
      if (!technicianId) return "未分配";

      // 如果已经是员工对象，直接返回用户名
      if (typeof technicianId === "object") {
        return technicianId.username || technicianId.name || "未分配";
      }

      // 优先从employees数组中查找
      if (this.employees && this.employees.length > 0) {
        const employee = this.employees.find(
          (emp) =>
            emp.id === technicianId ||
            emp._id === technicianId ||
            emp.username === technicianId
        );
        if (employee) return employee.username;
      }

      // 如果technicianId本身就是员工名称，直接返回
      if (
        typeof technicianId === "string" &&
        technicianId.length > 0 &&
        technicianId !== "未分配"
      ) {
        return technicianId;
      }

      return "未分配";
    },
  },
};
</script>

<style scoped>
.custom-calendar {
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
  overflow: hidden;
}

.calendar-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 20px;
  border-bottom: 1px solid #e4e7ed;
  background: #f8f9fa;
}

.calendar-nav {
  display: flex;
  align-items: center;
  gap: 16px;
}

.current-week {
  font-weight: 500;
  color: #303133;
}

.calendar-body {
  display: flex;
  height: 600px;
  overflow: hidden;
}

.calendar-grid {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  overflow: auto;
}

.calendar-header-row {
  display: flex;
  position: sticky;
  top: 0;
  z-index: 100;
  background: #f8f9fa;
  border-bottom: 1px solid #e4e7ed;
  height: 60px;
  flex-shrink: 0;
}

.time-header-cell {
  width: 80px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 500;
  border-right: 1px solid #e4e7ed;
  background: #f8f9fa;
  flex-shrink: 0;
}

.day-header-cell {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border-right: 1px solid #e4e7ed;
  background: #f8f9fa;
}

.day-header-cell:last-child {
  border-right: none;
}

.calendar-content {
  display: flex;
  flex: 1;
}

.time-column {
  width: 80px;
  background: #f8f9fa;
  border-right: 1px solid #e4e7ed;
  flex-shrink: 0;
}

.time-slot {
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-bottom: 1px solid #e4e7ed;
  font-size: 12px;
  color: #606266;
}

.days-grid {
  display: flex;
  flex: 1;
}

.day-column {
  flex: 1;
  border-right: 1px solid #e4e7ed;
  position: relative;
}

.day-column:last-child {
  border-right: none;
}

.hour-slots {
  height: 100%;
  position: relative;
}

.hour-slot {
  height: 60px;
  border-bottom: 1px solid #f0f0f0;
  position: relative;
  cursor: pointer;
  transition: background-color 0.2s;
  z-index: 1;
}

.hour-slots {
  height: 100%;
  position: relative;
}

.hour-slot:hover {
  background-color: #e8f4ff;
  border: 1px dashed #409eff;
}

.hour-slot:hover .add-hint {
  opacity: 0.6;
}

.hour-slot:active {
  background-color: #d9ecff;
}

.hour-slot:active .add-hint {
  opacity: 0.8;
}

.hour-slot.has-event {
  cursor: default;
}

.hour-slot.has-event:hover {
  background-color: #f5f7fa;
  border: none;
}

.event-block {
  position: absolute;
  border-radius: 4px;
  padding: 1px 2px;
  color: white;
  font-size: 11px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
  transition: all 0.2s;
  user-select: none;
  z-index: 5;
  overflow: hidden;
  cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.2);
  pointer-events: auto;
  will-change: transform; /* 优化性能 */
}

.event-block.editable {
  cursor: grab;
}

.event-block:hover {
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
  transform: translateY(-1px);
}

.event-block.drag-over {
  border: 2px dashed #1890ff;
  background-color: rgba(24, 144, 255, 0.1);
  transform: scale(1.02);
}

.event-block.editable:active {
  cursor: grabbing;
}

.event-content {
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  pointer-events: none;
  padding: 2px;
  gap: 1px;
}

.event-title {
  font-weight: 500;
  font-size: 10px;
  line-height: 1.1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex-shrink: 0;
  margin-bottom: 1px;
}

.event-time {
  font-size: 8px;
  opacity: 0.9;
  line-height: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex-shrink: 0;
}

.event-tech {
  font-size: 8px;
  opacity: 0.8;
  line-height: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex-shrink: 0;
}

.resize-handles {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  pointer-events: none;
}

.resize-handle {
  position: absolute;
  left: 0;
  right: 0;
  height: 12px; /* 增加高度 */
  background: linear-gradient(
    to bottom,
    rgba(255, 255, 255, 0.8),
    rgba(255, 255, 255, 0.3)
  );
  pointer-events: auto;
  cursor: ns-resize;
  opacity: 0;
  transition: all 0.2s ease;
  z-index: 15;
  border: 1px solid rgba(255, 255, 255, 0.3);
}

.resize-handle.top {
  top: 0;
  border-radius: 4px 4px 0 0;
}

.resize-handle.bottom {
  bottom: 0;
  border-radius: 0 0 4px 4px;
}

.event-block:hover .resize-handle {
  opacity: 1;
}

.event-block:hover .resize-handle:hover {
  background: rgba(255, 255, 255, 0.8);
}

/* 拖拽状态 */
.event-block.dragging {
  z-index: 1000;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
  transform: scale(1.02);
}

.event-block.resizing {
  z-index: 1000;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}

/* 边缘悬停状态 */
.event-block.hover-top {
  cursor: ns-resize;
}

.event-block.hover-bottom {
  cursor: ns-resize;
}

/* 增强的调整手柄悬停效果 */
.resize-handle:hover {
  background: linear-gradient(
    to bottom,
    rgba(255, 255, 255, 1),
    rgba(255, 255, 255, 0.6)
  );
  box-shadow: 0 0 8px rgba(255, 255, 255, 0.8);
  transform: scaleY(1.2);
}

/* 拖拽时的视觉反馈 */
.event-block.dragging {
  z-index: 1000;
  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
  transform: scale(1.02);
  border: 2px solid rgba(255, 255, 255, 0.5);
}

.event-block.resizing {
  z-index: 1000;
  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
  border: 2px solid rgba(255, 255, 255, 0.5);
}

/* 抽屉样式 */
.drawer-content {
  padding: 20px;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.drawer-form {
  flex: 1;
  overflow-y: auto;
}

.drawer-footer {
  border-top: 1px solid #e4e7ed;
  padding-top: 20px;
  text-align: right;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .calendar-body {
    flex-direction: column;
    height: auto;
  }

  .time-column {
    width: 60px;
  }

  .time-slot {
    height: 40px;
    font-size: 11px;
  }

  .hour-slot {
    height: 40px;
  }

  .event-block {
    font-size: 11px;
    padding: 2px;
  }
}
</style>
